﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace ICalendar.CalendarProperties
{

    /// <summary>
    /// This class can be a Date or a DateTime 
    /// </summary>
    [Serializable]
    public abstract class HybridDateTimeBase : CalendarPropertyBase<DateTime>
    {
        private TimeZoneInfo timeZone;

        /// <summary>
        /// To specify the identifier for the time zone definition for a time component in the property value
        /// </summary>
        public TimeZoneInfo TimeZone
        {
            get { return timeZone; }
            set
            {
                lock (this)
                {
                    timeZone = value;
                    this.Value = TimeZoneInfo.ConvertTime(Value, value);
                }
            }
        }

        private ValueType valueType;
        public ValueType ValueType
        {
            get { return valueType; }
            set
            {
                if (value != ValueType.Date && value != ValueType.DateTime)
                    throw new ArgumentOutOfRangeException("value", "The value type must be Date or DateTime.");
                valueType = value;
            }
        }

        protected HybridDateTimeBase(DateTime date)
        {
            this.Value = date;
            this.valueType = ValueType.DateTime;
        }

        protected override void SetValue(string value)
        {
            //(this.TimeZone.Id)
            //System.Globalization.DaylightTime b = new System.Globalization.DaylightTime()
            DateTime result;
            bool isOK = DateTime.TryParse(value, out result);
            this.Value = isOK ? result : DateTime.MinValue;
        }

        protected override string GetValue()
        {
            if (this.TimeZone != null)
            {
                this.Value = TimeZoneInfo.ConvertTime(Value, TimeZone);
            }
           
            //TODO:ALL ARE UTC FROM NOW, THE TZID I'LL BE USED WITH VTIMEZONE COMPLETED
            switch (valueType)
            {
                case ValueType.Date:
                    return  this.Value.ToICalendarDateString();
                case ValueType.DateTime:
                    return TimeZone == null  ? this.Value.ToICalendarUniversalTimeString() : this.Value.ToICalendarDateTimeString();
                default:
                    throw new ArgumentOutOfRangeException();
            }
        
        }

        protected override void SetParametersFromXParameters(XParameterCollection xparams)
        {
            if (xparams == null)
                return;

            string value = xparams.GetValue("VALUE");
            this.ValueType = string.IsNullOrEmpty(value)
                                 ? ValueType.DateTime
                                 : value.ToUpperInvariant() == "DATE"
                                       ? ValueType.Date
                                       : value.ToUpperInvariant() == "DATETIME" ? ValueType.DateTime : ValueType.DateTime;
            string tzId = xparams.GetValue("TZID");
            this.TimeZone = string.IsNullOrEmpty(tzId) ? null : TimeZoneInfo.FindSystemTimeZoneById(tzId);
        }

        protected override XParameterCollection GetXParametersFromParameters()
        {
            switch (ValueType)
            {
                case ValueType.Date:
                    return new XParameterCollection { { "VALUE", "DATE" } };
                default:
                    return new XParameterCollection
                        {
                            {"VALUE","DATETIME"},
                            {"TZID", this.TimeZone != null ? this.TimeZone.Id : null},
                        };
            }
        }

        protected override string[] GetXReservedParametersNames()
        {
            return new[] {"TZID"};
        }
    }
}
